<?php
use Doctrine\Common\Cache\ZendCache;
require_once 'Doctrine/Common/ClassLoader.php';

use Doctrine\Common\ClassLoader,
Doctrine\ORM\Configuration,
Doctrine\ORM\EntityManager,
Doctrine\ORM\Mapping\Driver\YamlDriver,
Doctrine\ORM\Mapping\Driver\XmlDriver,
Doctrine\ORM\Mapping\Driver\PHPDriver,
Doctrine\Common\Cache\ApcCache,
Doctrine\Common\Cache\MemcacheCache,
Doctrine\Common\Cache\XcacheCache,
Doctrine\Common\Cache\ArrayCache;

$classLoader = new ClassLoader('Doctrine');
$classLoader->register();

$classLoader = new ClassLoader('Entities', APPLICATION_PATH . '/data');
$classLoader->register();

/**
 * Class description
 *
 * @since 18 июня 201
 * @author diotheos
 */
class Lib_Application_Resource_Doctrine2 extends Zend_Application_Resource_ResourceAbstract
{
	/**
	 * Configuration options for Doctrine.
	 *
	 * @var \Doctrine\ORM\Configuration
	 */
	protected $_config;

	/**
	 * Initialize Doctrine.
	 *
	 * @return Doctrine\ORM\EntityManager
	 */
	public function init(){
		$options = $this->getOptions();

		$this->_config = new Configuration;

		// Metadata driver
		$this->_initMetadataDriver();

		$this->_initEntities();

		// Parameters
		$this->_initParameters();

		// Set up caches
		$this->_initCache();

		// Proxy configuration
		$this->_initProxy();

		// Database connection information
		$connectionOptions = $this->_initConnection();

		// Create EntityManager
		$em = EntityManager::create($connectionOptions, $this->_config);
                $em->getEventManager()->addEventSubscriber(new \Doctrine\DBAL\Event\Listeners\MysqlSessionInit('utf8', 'utf8_unicode_ci'));
		$this->getBootstrap()->getContainer()->em = $em;

		return $em;
	}
	/**
	 * Initialize metadata driver from resource options.
	 *
	 * @return void
	 */
	protected function _initMetadataDriver()
	{
		$options = $this->getOptions();

		$mappingPaths = $options['metadata']['mappingPaths'];

		$driver = $options['metadata']['driver'];
		switch($driver) {
			case 'yaml':
				$driver = new YamlDriver($mappingPaths);
				break;

			case 'xml':
				$driver = new XmlDriver($mappingPaths);
				break;

			case 'php':
				$driver = new PhpDriver($mappingPaths);
				break;

			default:
				$driver = $this->_config->newDefaultAnnotationDriver($mappingPaths);
		}

		$this->_config->setMetadataDriverImpl($driver);
	}
    /**
     * Initialize autoloading
     */
    protected function _initEntities()
    {
        $options = $this->getOptions();
        foreach($options['metadata']['entitiesPaths'] as $namespace => $path){
            //echo $namespace."-".$path;
            $classLoader = new ClassLoader($namespace, $path);
            $classLoader->register();
        }
    }
	/**
	 * Initialize Doctrine cache configuration from resource options.
	 *
	 * @return void
	 */
	protected function _initCache()
	{
		$options = $this->getOptions();
		if(!isset($options['cache']['metadata']['driver']))return false;
		switch($options['cache']['metadata']['driver']) {
			case 'apc':
				$mCache = new ApcCache();
				break;

			case 'memcache':
				$mCache = new MemcacheCache();
                                $mCache->setNamespace($options['cache']['metadata']['namespace']);

                                $memcache = new Memcache();
                                $memcache->connect($options['cache']['metadata']['host'], $options['cache']['metadata']['port']);

                                $mCache->setMemcache($memcache);
				break;

			case 'xcache':
				$mCache = new XcacheCache();
				break;

			default:
				$mCache = new ArrayCache();
		}
         switch($options['cache']['result']['driver']) {
			case 'apc':
				$rCache = new ApcCache();
				break;

			case 'memcache':
                                $rCache = new MemcacheCache();
                                $rCache->setNamespace($options['cache']['result']['namespace']);

                                $memcache = new Memcache();
                                $memcache->connect($options['cache']['result']['host'], $options['cache']['result']['port']);

                                $rCache->setMemcache($memcache);
				break;

		    case 'zend':
		        $rCache = new ZendCache();
		        $rCache->setNamespace($options['cache']['result']['namespace']);
		        $cacher = $this->getBootstrap()->getApplication()->getBootstrap()->getResource('Redis');
		        $rCache->setCache($cacher);
		        break;
			case 'xcache':
				$rCache = new XcacheCache();
				break;
			default:
				$rCache = new ArrayCache();
		}
		$this->_config->setMetadataCacheImpl($mCache);
		$this->_config->setQueryCacheImpl($rCache);
	}

	/**
	 * Initialize Doctrine proxy configuration from resource options.
	 *
	 * @return void
	 */
	protected function _initProxy()
	{
		$options = $this->getOptions();
		$this->_config->setProxyDir(isset($options['proxy']['directory']) ? $options['proxy']['directory'] : APPLICATION_PATH . '/data/doctrine2/Proxies');
		$this->_config->setProxyNamespace(isset($options['proxy']['namespace']) ? $options['proxy']['namespace'] : 'Proxies');
	}

	/**
	 * Initialize Doctrine connection configuration from resource options.
	 *
	 * @return void
	 */
	protected function _initConnection()
	{
		$options = $this->getOptions();
		return $options['connection'];
	}


	/**
	 * Save Doctrine parameters for latter retrieving.
	 *
	 * @return void
	 */
	protected function _initParameters()
	{
		$options = $this->getOptions();
		$container = $this->getBootstrap()->getApplication()->getBootstrap()->getContainer();
		Zend_Registry::set('doctrine.config', array(
                'doctrine.orm.mapping_paths' => $options['metadata']['mappingPaths'],
                'doctrine.orm.entities_paths' => $options['metadata']['entitiesPaths']
		));
	}
}